﻿using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Configuration.Provider;
using SubSonic.Security.Data;

namespace SubSonic.Security{
    public class RoleProvider : System.Web.Security.RoleProvider{

        public override void Initialize(string name, NameValueCollection config){
            if (config == null)
                throw new ArgumentNullException("config");

            base.Initialize(name, config);

            ApplicationName = config["ApplicationName"].ToString();
            config.Remove("ApplicationName");

            _provname = name;

            if (config.Count > 0){
                string key = config.GetKey(0);
                if (!string.IsNullOrEmpty(key))
                    throw new ProviderException("Unrecognized provider attribute: " + key);
            }

        }

        private string _provname = string.Empty;
        public override string Name{
            get { return _provname; }
        }

        private string _appname = string.Empty;
        public override string ApplicationName{
            get { return _appname; }
            set { _appname = value; }
        }


        #region Role
        public override void CreateRole(string roleName){
            Role r = new Role();
            r.RoleID = Guid.NewGuid();
            r.RoleName = roleName;
            r.IsNew = true;
            r.Save();
        }

        public override bool DeleteRole(string roleName, bool throwOnPopulatedRole){
            return (Role.Delete(Role.Columns.RoleName, roleName) > 0 );
        }

        public override bool RoleExists(string roleName){
            Role r = new Role(Role.Columns.RoleName, roleName);
            return r.IsLoaded;
        }

        public override bool IsUserInRole(string username, string roleName){
            return (bool)SPs.UserInRole(username, roleName, false).ExecuteScalar();
        }
        #endregion

        #region Get UserOrRole
        public override string[] FindUsersInRole(string roleName, string usernameToMatch){
            List<string> thelist = new List<string>();

            string[] usersintherole = GetUsersInRole(roleName);
            foreach (string usr in usersintherole)
                if (usr.ToLower().Contains(usernameToMatch.ToLower()))
                    thelist.Add(usr);

            return thelist.ToArray();
        }

        public override string[] GetUsersInRole(string roleName){
            Role r = new Role(Role.Columns.RoleName, roleName);
            UsersInRoleCollection urcol = r.UsersInRoles();
            List<string> lis = new List<string>();

            foreach (UsersInRole ur in urcol)
                lis.Add(ur.User.Username);

            return lis.ToArray();
        }

        public override string[] GetAllRoles(){
            List<string> ret = new List<string>();
            RoleCollection rolecol = new RoleCollection().Load();

            foreach (Role r in rolecol)
                ret.Add(r.RoleName);

            return ret.ToArray();
        }

        public override string[] GetRolesForUser(string username){
            List<string> theList = new List<string>();

            User u = new User(User.Columns.Username, username);

            UsersInRoleCollection col = u.UsersInRoles();
            foreach (UsersInRole ur in col)
                theList.Add(ur.Role.RoleName);

            return theList.ToArray();

        }

        #endregion

        #region User & Role

        public override void AddUsersToRoles(string[] usernames, string[] roleNames){
            foreach (string u in usernames)
                foreach (string r in roleNames)
                    SPs.AddUserToRole(u, r).Execute();
        }

        public override void RemoveUsersFromRoles(string[] usernames, string[] roleNames){
            foreach (string u in usernames)
                foreach (string r in roleNames)
                    SPs.DeleteUserFromRole(u, r).Execute();
        }

        #endregion   

        

        
    }
}